home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Snippets / Relative Time Strings / Relative Time Strings.c < prev    next >
Encoding:
Text File  |  1994-11-08  |  23.1 KB  |  754 lines  |  [TEXT/KAHL]

  1. /*====================================================================================
  2.     File:            Relative Time Strings.c
  3.     Written by:        Chris Hufford  CIS: 70076,1707
  4.                     Geoff Hufford  CIS: 72627,3511
  5.     
  6.     Description:    
  7.         These routines were written for and used in our Shareware program called
  8.         Eye On The Clock. These routines will take two dates and times and create a
  9.         string, in MANY different formats, of how much time there is between the two
  10.         dates and times. Basically you need to load up the Count_Rec structure and call
  11.         Get_Rel_Time_Str and your done.
  12.         
  13.         These routines reference 'STR#' resource 129 for all text used to build the string
  14.         
  15.         There are many supporting routines for both time/date stuff as well as strings
  16.         which may be useful on their own.
  17.     
  18.     Here is an example of loading up the Count_Rec:
  19.     
  20.         Count_Rec        time_rec;
  21.         Str255            the_str;
  22.     
  23.     time_rec.Display.fractional        = FALSE;
  24.     time_rec.Display.significant     = FALSE;
  25.     time_rec.Display.count_days     = FALSE;
  26.     time_rec.Display.hide_zeros     = FALSE;
  27.     time_rec.Display.allow_clock_display = FALSE;
  28.     time_rec.Display.allow_day_rounding  = FALSE;
  29.     time_rec.Display.abbreviated     = FALSE;
  30.  
  31.     time_rec.Target_In_Secs = 2840227200;            // target time to display (in seconds) 1/1/90
  32.     time_rec.From_In_Secs   = 3000000000;            // from time to display (in seconds)
  33.  
  34.     // you may add only the items which you want displayed:
  35.     time_rec.Display.display_items = year + month + week + day + hour + minute + second;
  36.     
  37.     Get_Rel_Time_Str (&time_rec, the_str);
  38.     // then display or use the_str)
  39. =====================================================================================*/
  40.  
  41. ////////////////////////
  42. // Includes
  43. ////////////////////////
  44. #include "Relative Time Strings.h"
  45.  
  46. ////////////////////////
  47. //    Internal Prototypes
  48. ////////////////////////
  49. void Setup_Significant (Display_Items* display, Display_Type_Ptr display_ptr, unsigned long the_secs);
  50. unsigned long Month_Secs(short the_month, short the_year);
  51. void Float2String (float the_num, Str255 the_string, short places);
  52. void Append_String (Str255 source_string, Str255 append_string, Boolean trailing_space);
  53. void Append_Num2String (long the_num, Str255 the_string, Boolean leading_zero);
  54. void Append_Seperator( Str255 the_str );
  55. void Determine_Display_Elements (Display_Type_Ptr display);
  56.  
  57. ////////////////////////
  58. //    Constants
  59. ////////////////////////
  60. enum{
  61.     Time_StringsID     =129,
  62.     yearString        =1,
  63.     yearsString,
  64.     yrString,
  65.     monthString,
  66.     monthsString,
  67.     moString,
  68.     weekString,
  69.     weeksString,
  70.     wkString,
  71.     dayString,
  72.     daysString,
  73.     dString,
  74.     hourString,
  75.     hoursString,
  76.     hString,
  77.     minuteString,
  78.     minutesString,
  79.     mString,
  80.     secondString,
  81.     secondsString,
  82.     sString,
  83.     agoString,
  84.     untilString,
  85.     countdaysString
  86.     };
  87.  
  88. /*====================================================================================
  89.     Name:                        Get_Rel_Time_Str
  90.     Description:
  91.         Send it a Count_Rec_Ptr and it will return a formated string of the time
  92.         difference between the two times sent in the Count_Rec
  93.     Last revision:    
  94.    __________________________________________________________________________________
  95.  
  96.     Input:
  97.          Count_Rec_Ptr    pointer to a Count_Rec structure which should be loaded with
  98.                          a from time, a to time, and all display options
  99.          the_str            pointer to a Str255 which will be used to return the string
  100.     Output:
  101.         the_str            the returned formated string
  102. =====================================================================================*/
  103. void Get_Rel_Time_Str (Count_Rec_Ptr count_ptr, Str255 the_str)
  104. {
  105.         Display_Elements    elements;
  106.         
  107.     Determine_Display_Elements (&count_ptr->Display);
  108.     Calculate_Rel_Time_Str(count_ptr, &elements);
  109.     Assemble_Time_String (&elements, the_str, count_ptr->Display.abbreviated);
  110. }
  111.     
  112.  
  113. /*====================================================================================
  114.     Name:                        Calculate_Rel_Time_Str
  115.     Description:
  116.         You must call Determine_Display_Elements at some point before making this call.
  117.         This is used by Get_Rel_Time_Str but could be useful to call on it's own. It
  118.         is passed a pointer to a Count_Rec and a pointer to Display_Elements. It does
  119.         everything needed to load Display_Elements which is used to assemble the output
  120.         string by Assemble_Time_String.
  121.     Last revision:    
  122.    __________________________________________________________________________________
  123.  
  124.     Input:
  125.          Count_Rec_Ptr            pointer to the Count_Rec that is being calculated
  126.          Display_Elements_Ptr    pointer to an empty Display_Elements which will be
  127.                                  filled upon exit
  128.     Output:
  129.         Display_Elements_Ptr    returns filled up and ready for Assemble_Time_String
  130. =====================================================================================*/
  131. void Calculate_Rel_Time_Str (Count_Rec_Ptr count_ptr, Display_Elements_Ptr element_ptr)
  132. {
  133.         long                current_day, temp;
  134.         long                next_year, next_month, offset = 0;
  135.         unsigned long        target_secs, current_secs;
  136.         unsigned long        years,months,weeks,days,hours,minutes,seconds,the_secs;
  137.         float                fraction;
  138.         Boolean                in_past, keep_counting;
  139.         Display_Items        display;
  140.         Display_Type_Ptr    display_ptr;
  141.         DateTimeRec            current_daterec, target_daterec;
  142.         short                places, year_index, month_index, four_years=0;
  143.  
  144.  
  145.     target_secs = count_ptr->Target_In_Secs;
  146.     current_secs = count_ptr->From_In_Secs;
  147.     
  148.     display_ptr = &count_ptr->Display;
  149.     display = display_ptr->display_items;
  150.  
  151.     if (target_secs < current_secs)
  152.     {
  153.         in_past = TRUE;
  154.         the_secs = current_secs - target_secs;
  155.         if (display_ptr->significant)
  156.             Setup_Significant (&display, display_ptr, the_secs);                
  157.         offset = target_secs % DAY_SECS;    // Calculate Offset to Round Days to Midnight
  158.     }
  159.     else
  160.     {
  161.         in_past = FALSE;
  162.         the_secs = target_secs - count_ptr->From_In_Secs;
  163.         if (display_ptr->significant)
  164.             Setup_Significant (&display, display_ptr, the_secs);                
  165.         offset = DAY_SECS - (target_secs % DAY_SECS);  // Calculate Offset to Round Days to Midnight
  166.     }
  167.         
  168.     if (display_ptr->last_item & calendarDayMask && !display_ptr->fractional && display_ptr->allow_day_rounding)
  169.     {
  170.         the_secs += offset;                            // Apply calendar day offset
  171.         offset = 0;                                    // Zero it so it cant be applied twice
  172.     }
  173.     
  174.     if (display_ptr->count_days && in_past)    // if we should count event date then add a day to past
  175.     {
  176.         the_secs += DAY_SECS;        //  events
  177.         the_secs += offset;            // Apply calendar day offset if it wasnt already
  178.         display = day;
  179.         element_ptr->count_days = TRUE;
  180.     }
  181.     else
  182.         element_ptr->count_days = FALSE;
  183.         
  184.     years = months = weeks = days = hours = minutes = seconds = 0;
  185.  
  186.     if (display & year || display & month)            // Otherwise simply calulate seconds
  187.     {
  188.         Secs2Date(current_secs, ¤t_daterec);
  189.         Secs2Date(target_secs, &target_daterec);
  190.         
  191.         four_years = (the_secs / FOUR_YEAR_SECS);    // FOUR_YEAR_SECS is a constant - 1461 days
  192.         the_secs -= four_years * FOUR_YEAR_SECS;
  193.         
  194.         year_index = current_daterec.year % 4;        // 0=leap,1-3=not leap
  195.  
  196.         if (in_past)
  197.         {
  198.             if (current_daterec.month < 3) year_index--;// Before March use the previous year
  199.             if (year_index == -1 || year_index == 3) year_index = 1;
  200.             else if (year_index == 1) year_index = 3;
  201.         }
  202.         else if (current_daterec.month > target_daterec.month && target_daterec.month >= 3)            
  203.                 year_index++;                        // After february use the next year
  204.         
  205.         keep_counting = TRUE;
  206.         while (keep_counting)   // Counts years until secs < the next year
  207.         {
  208.             if (year_index == 4 || year_index == 0)
  209.                 next_year = LEAP_YEAR_SECS;
  210.             else
  211.                 next_year = YEAR_SECS;
  212.                 
  213.             if (the_secs < next_year)
  214.                 keep_counting = FALSE;
  215.             else
  216.             {
  217.                 the_secs-= next_year;
  218.                 years++;
  219.                 year_index++;
  220.             }
  221.         }
  222.         years += four_years * 4;
  223.         
  224.         if (display & month)
  225.         {
  226.             month_index = current_daterec.month;
  227.             if (in_past)
  228.                 month_index--;
  229.             else
  230.             {    
  231.                 /****************************************************************
  232.                 *    The upcoming code deals with the following type of problem:    *
  233.                 *        1/30/94 -> 3/1/94 = one month away (2/30) doesn't exist    *
  234.                 *        so the current time is forced back to 1/28 (the same     *
  235.                 *        number of days as the month prior to the target)        *
  236.                 *                "1 month 1 day" is calculated                    *
  237.                 ****************************************************************/
  238.                 current_day = current_daterec.day;
  239.                 if (current_day > target_daterec.day)
  240.                 {
  241.                     current_day *= DAY_SECS;    // Convert to seconds since beginning of month
  242.                     temp = Month_Secs(target_daterec.month - 1, year_index); // Find length in Secs of prior month
  243.                     if (current_day > temp)        // Test if current date exists in prior month
  244.                         the_secs += current_day - temp;    // Slide current back enough days to make it exist
  245.                 }
  246.                 /***************************************************************/
  247.             } 
  248.  
  249.             keep_counting = TRUE;
  250.             while (keep_counting)
  251.             {
  252.                 if (month_index == 13)
  253.                     month_index = 1;
  254.                 else if (month_index == 0)
  255.                         month_index = 12;
  256.                     
  257.                 next_month = Month_Secs (month_index, year_index);
  258.  
  259.                 /****************************************************************
  260.                 *    The upcoming code deals with the following type of problem:    *
  261.                 *        4/30/94 -> 3/1/94 = would say "2mo 1dys                    *
  262.                 *        instead "1 month 28 days" is correctly calculated        *
  263.                 ****************************************************************/
  264.                 if (in_past)
  265.                     if (month_index == target_daterec.month-1)
  266.                         if (next_month < (current_daterec.day * DAY_SECS))
  267.                             keep_counting = FALSE;
  268.                 /***************************************************************/
  269.                 
  270.                 if (keep_counting)
  271.                 {
  272.                     if (the_secs < next_month)
  273.                         keep_counting = FALSE;
  274.                     else
  275.                     {
  276.                         the_secs -= next_month;
  277.                         months++;
  278.                         if (!in_past)
  279.                             month_index++;
  280.                         else 
  281.                             month_index--;
  282.                     }
  283.                 }
  284.             }
  285.             if ( ~display & year)
  286.             {
  287.                 months += years * 12;
  288.                 years = 0;
  289.             }
  290.             if (!months && display_ptr->hide_zeros) display -= month;    // Dont show if its a zero
  291.         }
  292.         if (display & year)
  293.             if (!years && display_ptr->hide_zeros) display -= year;        // Dont show if its a zero
  294.     }
  295.     
  296.     if (display & week)
  297.     {
  298.         weeks = the_secs / WEEK_SECS;                         // Calculate number of Weeks
  299.         the_secs -= (weeks * WEEK_SECS);
  300.         if (!weeks && display_ptr->hide_zeros) display -= week;            // Dont show if its a zero
  301.     }
  302.  
  303.     if (display & day)
  304.     {
  305.         days = the_secs / DAY_SECS;                            // Calculate number of Days
  306.         the_secs -= (days * DAY_SECS);
  307.         if (!days && display_ptr->hide_zeros) display -= day;            // Dont show if its a zero
  308.     }
  309.  
  310.     if (display & hour)
  311.     {
  312.         hours = the_secs / HOUR_SECS;                        // Calculate number of Hours
  313.         the_secs -= (hours * HOUR_SECS);
  314.     }
  315.  
  316.     if (display & minute)
  317.     {
  318.         minutes = the_secs / MINUTE_SECS;
  319.         the_secs -= (minutes * MINUTE_SECS);
  320.     }
  321.  
  322.     if (display & second)  //Remove condition if we are going to convert to do noncalculated updates
  323.         seconds = the_secs;
  324.  
  325.     if (display_ptr->fractional && ~display_ptr->last_item & second)
  326.     {
  327.         switch (display_ptr->last_item)
  328.         {
  329.             case year:
  330.                 fraction = (float)the_secs / next_year;
  331.                 places = YEAR_PLACES;
  332.                 break;
  333.                 
  334.             case month:
  335.                 fraction = (float)the_secs / next_month;
  336.                 places = MONTH_PLACES;
  337.                 break;
  338.                 
  339.             case week:
  340.                 fraction = (float)the_secs / WEEK_SECS;
  341.                 places = WEEK_PLACES;
  342.                 break;
  343.                 
  344.             case day:
  345.                 fraction = (float)the_secs / DAY_SECS;
  346.                 places = DAY_PLACES;
  347.                 break;
  348.                 
  349.             case hour:
  350.                 fraction = (float)the_secs / HOUR_SECS;
  351.                 places = HOUR_PLACES;
  352.                 break;
  353.                 
  354.             case minute:
  355.                 fraction = (float)the_secs / MINUTE_SECS;
  356.                 places = MINUTE_PLACES;
  357.                 break;
  358.                 
  359.         }           
  360.         Float2String (fraction, element_ptr->fractional, places);
  361.     }
  362.     else element_ptr->fractional[0] = 0;
  363.     
  364.     display |= display_ptr->last_item;
  365.     element_ptr->inPast = in_past;
  366.     element_ptr->display_items = display;
  367.     element_ptr->last_item = display_ptr->last_item;
  368.     element_ptr->year = years;
  369.     element_ptr->month = (unsigned long)months;
  370.     element_ptr->week = weeks;
  371.     element_ptr->day = days;
  372.     element_ptr->hour = hours;
  373.     element_ptr->minute = minutes;
  374.     element_ptr->second = seconds;
  375.  
  376.     element_ptr->clockDisplay = (hours < 24 && display_ptr->clockDisplayEnable);  //Turn on Clock display
  377. }
  378.  
  379.  
  380. /*====================================================================================
  381.     Name:                        Assemble_Time_String
  382.     Description:
  383.         Send it a Display_Elements_Ptr which has been previously filled by
  384.         Calculate_Rel_Time_Str, send it a string and a Boolean and it returned the
  385.         formatted relative time string.
  386.     Last revision:    
  387.    __________________________________________________________________________________
  388.  
  389.     Input:
  390.          Display_Elements_Ptr    pointer to a filled Display_Elements
  391.          Str255                    pointer to a string to be returned
  392.          Boolean    abrev_string    TRUE = abbreviated string returned
  393.                                  FALSE = full string returned
  394.     Output:
  395.         Str255                    formatted output string
  396. =====================================================================================*/
  397. void Assemble_Time_String (Display_Elements_Ptr element_ptr, Str255 the_str, Boolean abrev_string)
  398. {
  399.         Boolean singular;
  400.         Display_Items display, frac_display = 0;
  401.         Str255  temp_str;
  402.  
  403.     the_str[0] = 0;
  404.  
  405.     display = element_ptr->display_items;
  406.     if (element_ptr->fractional[0])
  407.         frac_display = element_ptr->last_item;
  408.  
  409.     if (element_ptr->count_days)
  410.     {
  411.         GetIndString(temp_str, Time_StringsID, countdaysString);
  412.         Append_String (the_str, temp_str, 1);
  413.         Append_Num2String (element_ptr->day,the_str,FALSE);
  414.         return;
  415.     }
  416.  
  417.     
  418.     if (display & year)
  419.     {
  420.         singular = FALSE;
  421.         Append_Num2String (element_ptr->year,the_str,FALSE);
  422.         if (frac_display & year)
  423.             Append_String (the_str, element_ptr->fractional, 0);
  424.         else
  425.             if (element_ptr->year == 1)
  426.                 singular = TRUE;
  427.         
  428.         if (abrev_string)
  429.             GetIndString(temp_str, Time_StringsID, yrString);
  430.         else
  431.         {
  432.             GetIndString(temp_str, Time_StringsID, singular ? yearString:yearsString);      
  433.             the_str[++the_str[0]] = NUMBER_SEPARATOR;
  434.         }                    
  435.         Append_String (the_str, temp_str, 1);
  436.     }
  437.  
  438.  
  439.     if (display & month)
  440.     {
  441.         singular = FALSE;
  442.         Append_Num2String (element_ptr->month,the_str,FALSE);
  443.         if (frac_display & month)
  444.             Append_String (the_str, element_ptr->fractional, 0);
  445.         else if (element_ptr->month == 1) singular = TRUE;
  446.  
  447.         if (abrev_string)
  448.             GetIndString(temp_str, Time_StringsID, moString);
  449.         else
  450.         {
  451.             GetIndString(temp_str, Time_StringsID, singular ? monthString:monthsString);    
  452.             the_str[++the_str[0]] = NUMBER_SEPARATOR;
  453.         }                    
  454.         Append_String (the_str, temp_str, 1);
  455.     }
  456.  
  457.  
  458.     if (display & week)
  459.     {
  460.         singular = FALSE;
  461.         Append_Num2String (element_ptr->week,the_str,FALSE);
  462.         if (frac_display & week)
  463.             Append_String (the_str, element_ptr->fractional, 0);
  464.         else if (element_ptr->week == 1) singular = TRUE;
  465.  
  466.         if (abrev_string)
  467.             GetIndString(temp_str, Time_StringsID, wkString);
  468.         else
  469.         {
  470.             GetIndString(temp_str, Time_StringsID, singular ? weekString:weeksString);      
  471.             the_str[++the_str[0]] = NUMBER_SEPARATOR;
  472.         }                    
  473.         Append_String (the_str, temp_str, 1);
  474.     }
  475.  
  476.  
  477.     if (display & day)
  478.     {
  479.         singular = FALSE;
  480.         Append_Num2String (element_ptr->day,the_str,FALSE);
  481.         if (frac_display & day)
  482.             Append_String (the_str, element_ptr->fractional, 0);
  483.         else if (element_ptr->day == 1) singular = TRUE;
  484.  
  485.         if (abrev_string)
  486.             GetIndString(temp_str, Time_StringsID, dString);
  487.         else
  488.         {
  489.             GetIndString(temp_str, Time_StringsID, singular ? dayString:daysString);    
  490.             the_str[++the_str[0]] = NUMBER_SEPARATOR;
  491.         }                    
  492.         Append_String (the_str, temp_str, 1);
  493.     }
  494.  
  495.  
  496.     if (element_ptr->clockDisplay)
  497.     {
  498.         Append_Num2String (element_ptr->hour,the_str,FALSE);
  499.         Append_Seperator(the_str);
  500.         Append_Num2String (element_ptr->minute,the_str,TRUE);
  501.         if (frac_display & minute)
  502.             Append_String (the_str, element_ptr->fractional, 0);
  503.         if (display & second)
  504.         {
  505.             Append_Seperator(the_str);
  506.             Append_Num2String (element_ptr->second,the_str,TRUE);
  507.         }
  508.         the_str[++the_str[0]] = ' ';
  509.     }
  510.     else
  511.     {
  512.         if (display & hour)
  513.         {
  514.             singular = FALSE;
  515.             Append_Num2String (element_ptr->hour,the_str,FALSE);
  516.             if (frac_display & hour)
  517.                 Append_String (the_str, element_ptr->fractional, 0);
  518.             else if (element_ptr->hour == 1) singular = TRUE;
  519.     
  520.             if (abrev_string)
  521.                 GetIndString(temp_str, Time_StringsID, hString);
  522.             else
  523.             {
  524.                 GetIndString(temp_str, Time_StringsID, singular ? hourString:hoursString);      
  525.                 the_str[++the_str[0]] = NUMBER_SEPARATOR;
  526.             }                    
  527.             Append_String (the_str, temp_str, 1);
  528.         }
  529.  
  530.         if (display & minute)
  531.         {
  532.             singular = FALSE;
  533.             Append_Num2String (element_ptr->minute,the_str,FALSE);
  534.             if (frac_display & minute)
  535.                 Append_String (the_str, element_ptr->fractional, 0);
  536.             else if (element_ptr->minute == 1) singular = TRUE;
  537.     
  538.             if (abrev_string)
  539.                 GetIndString(temp_str, Time_StringsID, mString);
  540.             else
  541.             {
  542.                 GetIndString(temp_str, Time_StringsID, singular ? minuteString:minutesString);  
  543.                 the_str[++the_str[0]] = NUMBER_SEPARATOR;
  544.             }                    
  545.             Append_String (the_str, temp_str, 1);
  546.         }
  547.     
  548.         if (display & second)
  549.         {
  550.             Append_Num2String (element_ptr->second,the_str,FALSE);
  551.     
  552.             if (abrev_string)
  553.                 GetIndString(temp_str, Time_StringsID, sString);
  554.             else
  555.             {
  556.                 GetIndString(temp_str, Time_StringsID, element_ptr->second == 1 ? secondString:secondsString);  
  557.                 the_str[++the_str[0]] = NUMBER_SEPARATOR;
  558.             }                    
  559.             Append_String (the_str, temp_str, 1);
  560.         }
  561.     }
  562.  
  563.     GetIndString(temp_str, Time_StringsID, element_ptr->inPast ? agoString:untilString);    
  564.     Append_String (the_str, temp_str, 0);
  565. }
  566.  
  567.  
  568. /*********************************************
  569. *       Setup_Significant: 
  570. *               Sets Display to most significant Event
  571. **********************************************/
  572. void Setup_Significant (Display_Items* display, Display_Type_Ptr display_ptr,
  573.                                  unsigned long the_secs)
  574. {
  575.     if (the_secs < DAY_SECS && *display & hour && *display & minute && display_ptr->allow_clock_display)
  576.     {
  577.         display_ptr->clockDisplayEnable = TRUE;
  578.         if (display_ptr->display_items & second)
  579.         {
  580.             *display = (hour + minute + second);
  581.             display_ptr->last_item = second;
  582.         }
  583.         else
  584.         {
  585.             *display = (hour + minute);
  586.             display_ptr->last_item = minute;
  587.         }
  588.         return;
  589.     }
  590.     *display = display_ptr->last_item;
  591.     display_ptr->clockDisplayEnable = FALSE;
  592.     if (display_ptr->display_items & second) *display = second;
  593.     if (display_ptr->display_items & minute &&    the_secs >= MINUTE_SECS) *display = minute;
  594.     if (display_ptr->display_items & hour &&    the_secs >= HOUR_SECS)  *display = hour;
  595.     if (display_ptr->display_items & day &&        the_secs >= DAY_SECS)   *display = day;
  596.     if (display_ptr->display_items & week &&    the_secs >= WEEK_SECS)  *display = week;
  597.     if (display_ptr->display_items & month &&    the_secs >= (31 * DAY_SECS)) *display = month;
  598.     if (display_ptr->display_items & year &&    the_secs >= YEAR_SECS)  *display = year;
  599.     display_ptr->last_item = *display;
  600. }
  601.  
  602.  
  603. /*********************************************
  604. *       Determine_Display_Elements: 
  605. *               Sets Display Elements to be calculated
  606. **********************************************/
  607. void Determine_Display_Elements (Display_Type_Ptr display)
  608. {
  609.  
  610.     // FIND THE SMALLEST DISPLAY ITEM CHECKED
  611.     if (display->display_items & year)    display->last_item = year;
  612.     if (display->display_items & month)   display->last_item = month;
  613.     if (display->display_items & week)    display->last_item = week;
  614.     if (display->display_items & day)     display->last_item = day;
  615.     if (display->display_items & hour)    display->last_item = hour;
  616.     if (display->display_items & minute)  display->last_item = minute;
  617.     if (display->display_items & second)  display->last_item = second;
  618.  
  619.     // DETERMINE IF CLOCK DISPLAY WILL BE USED
  620.     if (display->display_items & hour && display->display_items & minute && display->allow_clock_display)
  621.         display->clockDisplayEnable = TRUE;
  622.     else
  623.         display->clockDisplayEnable = FALSE;
  624.  
  625. }
  626.  
  627.  
  628. /*******************************************
  629. *    Month_Secs: 
  630. *            Returns the number of seconds in a specified month
  631. **********************************************/
  632. unsigned long Month_Secs(short the_month, short the_year)
  633. {    
  634.     switch (the_month)
  635.     {
  636.         case 2:                            // February
  637.             if ((the_year % 4) == 0)    // Leap Year
  638.                 return 2505600;            // 29 days of seconds
  639.             else
  640.                 return 2419200;            // 28 days of seconds
  641.             break;
  642.  
  643.         case 4:                            // April
  644.         case 6:                            // June
  645.         case 9:                            // September
  646.         case 11:                        // November
  647.             return 2592000;                // 30 days of seconds
  648.             break;
  649.         
  650.         default:                        // The Rest of the months
  651.             return 2678400;                // 31 days of seconds
  652.             break;
  653.     }
  654. }
  655.  
  656. /*====================================================================================
  657.     Name:                        Append_String
  658.     Description:
  659.         send it a source string and an append string as well as a flag
  660.         which will add a trailing space to the output string
  661.     Last revision:    
  662.    __________________________________________________________________________________
  663.  
  664.     Input:
  665.          source_string
  666.          append_string
  667.          trailing_spaces flag
  668.     Output:
  669.         source_string will be the original string + append string + trailing_space (if any)
  670. =====================================================================================*/
  671. void Append_String (Str255 source_string, Str255 append_string, Boolean trailing_space)
  672. {
  673.     BlockMove(append_string + 1, source_string + source_string[0] + 1L, append_string[0]);
  674.     source_string[0] += append_string[0];
  675.     if (trailing_space)
  676.     {
  677.         source_string[source_string[0]+1] = ' ';
  678.         source_string[0]++;
  679.     }
  680. }
  681.  
  682. /*====================================================================================
  683.     Name:                        Append_Num2String
  684.     Description:
  685.         send it a number and it will return that number appended to the
  686.         string which you specify. Also, if leading_zero is true, it will first add a
  687.         zero to the string if the number is a single digit
  688.     Last revision:    
  689.    __________________________________________________________________________________
  690.  
  691.     Input:
  692.          the_num                number to append onto the string
  693.          the_string            string to append onto
  694.          leading_zero flag    TRUE = add a leading zero to single digit numbers
  695.                              FALSE = don't add a leading zero
  696.     Output:
  697.         the_string
  698. =====================================================================================*/
  699. void Append_Num2String (long the_num, Str255 the_string, Boolean leading_zero)
  700. {
  701.     Str255        temp_str;
  702.     
  703.     NumToString(the_num,temp_str);
  704.     if (leading_zero && the_num < 10)
  705.         the_string[++the_string[0]] = '0';
  706.     BlockMove(temp_str + 1, the_string + the_string[0] + 1L, temp_str[0]);
  707.     the_string[0] += temp_str[0];
  708. }
  709.  
  710. /*********************************************
  711. *
  712. *    Append_Seperator: appends the Time_Seperator character to the sent string
  713. *
  714. *
  715. **********************************************/
  716. void Append_Seperator( Str255 the_str )
  717. {
  718.     the_str[++the_str[0]] = ':';
  719. }
  720.  
  721. /*====================================================================================
  722.     Name:                        Float2String
  723.     Description:
  724.         Send it a float number less than 1 (just decimal places) and
  725.         it will append a decimal point and the number to the source string. The number
  726.         will have exactly 'places' number of digits.
  727.         THIS IS NOT A GREAT ROUTINE. IT ONLY DEALS WITH NUMBERS LESS THAN 1 AND GREATER
  728.         THAN 0.
  729.     Last revision:    
  730.    __________________________________________________________________________________
  731.  
  732.     Input:
  733.          the_num            a float number greater than 0 and less than 1
  734.          the_string        output string
  735.          places            number of decimal places you want in the output
  736.     Output:
  737.         the_string
  738. =====================================================================================*/
  739. void Float2String (float the_num, Str255 the_string, short places)
  740. {
  741.     Str255            dec_str;
  742.     register short     i;
  743.     
  744.     the_string[1] = '.';
  745.     the_string[0] = 1;
  746.     for (i=1; i <= places; i++)
  747.     {
  748.         the_num *= 10;
  749.         NumToString(the_num,dec_str);
  750.         the_num -= (int)the_num;
  751.         the_string[++the_string[0]] = dec_str[1];
  752.     }
  753. }
  754.